package com.ahy231.service.impl;

import com.ahy231.dto.FirstMessage;
import com.ahy231.dto.GetMessages;
import com.ahy231.entity.Message;
import com.ahy231.entity.User;
import com.ahy231.mapper.MessageMapper;
import com.ahy231.mapper.UserMapper;
import com.ahy231.service.MessageService;
import com.ahy231.utils.JWTUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.shiro.SecurityUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.sql.Timestamp;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author ahy231
 * @date 2021/7/28 14:25
 * @description
 */
@Service
public class MessageServiceImpl implements MessageService {

    private final MessageMapper messageMapper;
    private final UserMapper userMapper;

    public MessageServiceImpl(MessageMapper messageMapper, UserMapper userMapper) {
        this.messageMapper = messageMapper;
        this.userMapper = userMapper;
    }

    @Override
    public boolean sendMessage(Long userId, String message) {
        Long senderId = getUserId();
        Assert.notNull(senderId, "获取不到用户 id");
        Timestamp timestamp = new Timestamp(System.currentTimeMillis());
        Message instance = new Message(null, senderId, userId, message, timestamp, 1);
        messageMapper.insert(instance);
        return true;
    }

    @Override
    public PageInfo<GetMessages> getMessages(Long userId, Integer pageNum, Integer pageSize) {
        Long selfId = getUserId();
        Assert.notNull(selfId, "service 获取不到用户 id");
        Assert.notNull(userId, "联系人 id 不能为空");
        Page<GetMessages> page = PageHelper.startPage(pageNum, pageSize);
        List<GetMessages> messages = messageMapper.queryMessages(selfId, userId);
        messages.sort(Comparator.comparing(m -> Long.valueOf(m.getMessageId())));
        return PageInfo.of(page);
    }

    @Override
    public Boolean confirmMessage(Long messageId) {
        Long selfId = getUserId();
        Assert.notNull(selfId, "service 获取不到用户 id");
        Assert.isTrue(selfId.equals(messageMapper.selectById(messageId).getReceiverId()), "用户不是消息接收者");
        return messageMapper.updateById(new Message(messageId, null, null, null, null, 2)) > 0;
    }

    @Override
    public PageInfo<FirstMessage> firstMessage(Integer pageNum, Integer pageSize) {
        Long selfId = getUserId();
        List<Message> messages = messageMapper.selectList(new QueryWrapper<Message>().eq("sender_id", selfId).or().eq("receiver_id", selfId));
        messages.sort((m1, m2) -> -m1.getTime().compareTo(m2.getTime()));
        Map<Long, Message> userMessages = new HashMap<>();
        for (Message m : messages) {
            Long userId = Objects.equals(m.getSenderId(), selfId) ? m.getReceiverId() : m.getSenderId();
            userMessages.putIfAbsent(userId, m);
        }
        Set<Long> userIds = userMessages.keySet();
        List<User> users = userMapper.selectBatchIds(userIds);
        HashMap<Long, User> userMap = new HashMap<>();
        users.forEach(u -> userMap.put(u.getUserId(), u));
        List<FirstMessage> result = new ArrayList<>(userMessages.values()).stream().map(m -> FirstMessage.builder()
                .userId(Objects.equals(m.getSenderId(), selfId) ? m.getReceiverId() : m.getSenderId())
                .username(userMap.get(Objects.equals(m.getSenderId(), selfId) ? m.getReceiverId() : m.getSenderId()).getUsername())
                .imgUrl(userMap.get(Objects.equals(m.getSenderId(), selfId) ? m.getReceiverId() : m.getSenderId()).getImgUrl())
                .message(m.getContent())
                .time(m.getTime())
                .build()).sorted((m1, m2) -> -m1.getTime().compareTo(m2.getTime())).collect(Collectors.toList());
        PageInfo<FirstMessage> pageInfo;
        if (result.size() == pageSize) {
            pageInfo = PageInfo.of(result.subList((pageNum - 1) * pageSize, pageNum * pageSize));
            pageInfo.setPageNum(pageNum);
            pageInfo.setPageSize(pageSize);
            pageInfo.setPages((int) Math.ceil(result.size() / (double) pageSize));
        } else {
            pageInfo = PageInfo.of(result);
            pageInfo.setPageNum(1);
            pageInfo.setPageSize(result.size());
            pageInfo.setPages(1);
        }
        return pageInfo;
    }

    private Long getUserId() {
        return JWTUtil.getUserId(SecurityUtils.getSubject().getPrincipal().toString());
    }
}
